/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 *
 */

import { Configuration, Level, levels } from 'log4js';
import path from 'path';

import { PathUtil } from '../../common/util/path-util';
import { HVIGOR_PROJECT_ROOT_DIR } from '../../common/const/path-const';
import { HVIGOR_USER_HOME_DIR_NAME } from '../../common/const/const';

export const logFilePath = () => {
  let hvigorDataDir;
  try {
    hvigorDataDir = PathUtil.getHvigorCacheDir();
  } catch {
    hvigorDataDir = path.resolve(HVIGOR_PROJECT_ROOT_DIR, HVIGOR_USER_HOME_DIR_NAME);
  }
  const dir = './outputs/build-logs';
  return path.resolve(hvigorDataDir, dir);
};

let configuration: Configuration = {
  appenders: {
    debug: {
      type: 'stdout',
      layout: {
        type: 'pattern',
        pattern: '[%d] > hvigor %p %c %[%m%]',
      },
    },
    'debug-log-file': {
      type: 'file',
      filename: path.resolve(logFilePath(), 'build.log'),
      maxLogSize: 2 * 1024 * 1024,
      backups: 9,
      encoding: 'utf-8',
      level: 'debug',
    },
    info: {
      type: 'stdout',
      layout: {
        type: 'pattern',
        pattern: '[%d] > hvigor %[%m%]',
      },
    },
    'no-pattern-info': {
      type: 'stdout',
      layout: {
        type: 'pattern',
        pattern: '%m',
      },
    },
    wrong: {
      type: 'stderr',
      layout: {
        type: 'pattern',
        pattern: '[%d] > hvigor %[%p: %m%]',
      },
    },
    'just-debug': { type: 'logLevelFilter', appender: 'debug', level: 'debug', maxLevel: 'debug' },
    'just-info': { type: 'logLevelFilter', appender: 'info', level: 'info', maxLevel: 'info' },
    'just-wrong': { type: 'logLevelFilter', appender: 'wrong', level: 'warn', maxLevel: 'error' },
  },
  categories: {
    default: { appenders: ['just-debug', 'just-info', 'just-wrong'], level: 'debug' },
    'no-pattern-info': { appenders: ['no-pattern-info'], level: 'info' },
    'debug-file': { appenders: ['debug-log-file'], level: 'debug' },
  },
};

export const setConfiguration = (config: Configuration) => {
  configuration = config;
};

export const getConfiguration = () => {
  return configuration;
};

export const updateConfiguration = () => {
  const debugLogFile = configuration.appenders['debug-log-file'];
  if (debugLogFile && 'filename' in debugLogFile) {
    debugLogFile.filename = path.resolve(logFilePath(), 'build.log');
  }
  return configuration;
};

let contextLevel = levels.DEBUG;

export const setCategoriesLevel = (level: Level, ignoreLevelCategoryFilterArr?: string[]) => {
  contextLevel = level;
  const categories = configuration.categories;
  for (const category in categories) {
    if (ignoreLevelCategoryFilterArr?.includes(category) || category.includes('file')) {
      continue;
    }
    if (Object.prototype.hasOwnProperty.call(categories, category)) {
      categories[category].level = level.levelStr;
    }
  }
};

export const getLevel = () => {
  return contextLevel;
};

export const levelMap = new Map<string, Level>([
  ['ALL', levels.ALL],
  ['MARK', levels.MARK],
  ['TRACE', levels.TRACE],
  ['DEBUG', levels.DEBUG],
  ['INFO', levels.INFO],
  ['WARN', levels.WARN],
  ['ERROR', levels.ERROR],
  ['FATAL', levels.FATAL],
  ['OFF', levels.OFF],
  ['all', levels.ALL],
  ['mark', levels.MARK],
  ['trace', levels.TRACE],
  ['debug', levels.DEBUG],
  ['info', levels.INFO],
  ['warn', levels.WARN],
  ['error', levels.ERROR],
  ['fatal', levels.FATAL],
  ['off', levels.OFF],
]);
